{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "19241a08-66d4-4d41-b8f0-64ad9e672b1e",
   "metadata": {},
   "source": [
    "# Pandas_索引操作和高级索引\n",
    "## 索引对象\n",
    "- pandas中的索引都是index类对象，又称为索引对象，该对象是不可修改的，以保证数据的安全"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "58970267-2821-4490-8a58-e5b06abea2fe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Index(['a', 'b', 'c', 'd', 'e'], dtype='object')\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "ser_obj = pd.Series(range(5), index=['a','b','c','d','e'])\n",
    "ser_index = ser_obj.index\n",
    "print(ser_index)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe272a3c-a7e7-45e3-9b39-15f3518ea1cb",
   "metadata": {},
   "source": [
    "虽然index是不可变的，但是可以创建两个Series对象共用一个index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d560817e-27d6-4e97-8e28-058b08979663",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "ser_obj1 = pd.Series(range(3), index=['a','b','c'])\n",
    "ser_obj2 = pd.Series(['a','b','c'], index=ser_obj1.index)\n",
    "print(ser_obj2.index is ser_obj1.index)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f956b77-f269-4885-84b3-7c3b9ccc2570",
   "metadata": {},
   "source": [
    "【重要】\n",
    "- Index64Index: 针对整数特殊Index对象\n",
    "- MultiIndex: 层次化索引，表示单个轴上的多层索引\n",
    "- Datatimelndex: 存储纳秒级时间戳"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c938ec5-831e-4172-8edd-c2346759eaf0",
   "metadata": {},
   "source": [
    "## 重置索引\n",
    "- Pandas中提供了一个重要的方法是reindex(), 该方法的作用是对原索引和新索引进行匹配。也就是说，新索引包含原索引的程序，而原索引数据按照新索引排序，如果新索引中没有原索引的数据，那么程序会添加新的索引，并将值填充为NaN 或者使用 fill_values() 填充其他值\n",
    "- reindex()方法的语法格式：\n",
    "- DataFrame.reindex(labels+None, index=None, columns=None,\n",
    "                    axis=None, method=None, copy=True, level=None\n",
    "                    fill_value=nan, limit=None, tolerance=None)\n",
    "- index: 用所索引的新序列\n",
    "- method: 插入充值方式\n",
    "- fill_value: 引入缺失值时使用的替代值\n",
    "- limit: 前向或后向填充时的最大填充值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "5f1e30a1-df98-4112-b1e8-6fac070901b2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "c    1\n",
      "d    2\n",
      "a    3\n",
      "b    4\n",
      "e    5\n",
      "dtype: int64\n",
      "a    3.0\n",
      "b    4.0\n",
      "c    1.0\n",
      "d    2.0\n",
      "e    5.0\n",
      "f    NaN\n",
      "dtype: float64\n",
      "a    3\n",
      "b    4\n",
      "c    1\n",
      "d    2\n",
      "e    5\n",
      "f    6\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "ser_obj = pd.Series([1,2,3,4,5], index=['c','d','a','b','e'])\n",
    "print(ser_obj)\n",
    "\n",
    "#重新索引\n",
    "ser_obj2 = ser_obj.reindex(['a','b','c','d','e','f'])\n",
    "print(ser_obj2)\n",
    "\n",
    "#重新索引时，指定【填充缺失值】\n",
    "ser_obj3 = ser_obj.reindex(['a','b','c','d','e','f'], fill_value=6) \n",
    "print(ser_obj3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9673b37-e2a7-4952-acca-d9114fe8f088",
   "metadata": {},
   "source": [
    "fill_value 参数会让所有的缺失值都填充为同一个值。如果期望使用相邻元素值（前边或后边元素的值）进行填充，可以使用 method 参数，method 惨呼提供多个对应的参数值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dcf72b1f-9b88-4a93-a4bb-d8a72c5659ca",
   "metadata": {},
   "source": [
    "- ffill 或 pad: 前向填充值\n",
    "- hfill 或 backfill: 后向填充值\n",
    "- nearest: 从最近的索引填充"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "2cf58be8-1004-48e5-a1d3-b0aaf5f4b40d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0    1\n",
      "2    3\n",
      "4    5\n",
      "6    7\n",
      "dtype: int64\n",
      "0    1\n",
      "1    1\n",
      "2    3\n",
      "3    3\n",
      "4    5\n",
      "5    5\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "#创建Series对象，并为其指定索引\n",
    "ser_obj = pd.Series([1,3,5,7], index=[0,2,4,6])\n",
    "print(ser_obj)\n",
    "ser_obj1 = ser_obj.reindex(range(6), method='ffill')   #向前索引，重新填充值\n",
    "print(ser_obj1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0dc518b4-b0fd-4666-a821-ec9dc15d89fd",
   "metadata": {},
   "source": [
    "当method参数设置为ffill时，则会表示使用前一个索引对应的数据填充到缺失的位置，因此【索引'1'会填充索引'0'对应的的数据1，索引'2'会填充索引'2'对应的的数据3，以此类推】"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7477321f-ac3e-4523-9039-4fd242654d2d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0    1\n",
      "2    3\n",
      "4    5\n",
      "6    7\n",
      "dtype: int64\n",
      "0    1\n",
      "1    3\n",
      "2    3\n",
      "3    5\n",
      "4    5\n",
      "5    7\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "#创建Series对象，并为其指定索引\n",
    "ser_obj = pd.Series([1,3,5,7], index=[0,2,4,6])\n",
    "print(ser_obj)\n",
    "\n",
    "ser_obj1 = ser_obj.reindex(range(6), method='bfill')    #重新索引，向后填充值\n",
    "print(ser_obj1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da4243dd-aa06-4423-ac97-c66a42567e4c",
   "metadata": {},
   "source": [
    "当method参数设置为bfill时，则会表示使用前一个索引对应的数据填充到缺失的位置，因此【索引'1'会填充索引'2'对应的的数据3，索引'3'会填充索引'4'对应的的数据5，以此类推】"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23c6d0c8-8b21-4bdc-a25d-b3c8d25d17ed",
   "metadata": {},
   "source": [
    "## 索引操作\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "eaadb457-786f-4292-a0a4-26bae46eaa28",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "ser_obj = pd.Series([1,3,5,7], index=[0,2,4,6])\n",
    "print(ser_obj[2])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e92a3b82-0cd0-444a-950e-22e8bd176f37",
   "metadata": {},
   "source": [
    "使用切片"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a9a02150-22e9-4cd0-87da-0c9a00330fad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4    5\n",
      "6    7\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "ser_obj = pd.Series([1,3,5,7], index=[0,2,4,6])\n",
    "print(ser_obj[2:4])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5091f544-6bfd-446a-9b06-e224b76e4977",
   "metadata": {},
   "source": [
    "使用索引名称进行切片"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "daa0a952-143f-4bac-bd0e-49da06c13636",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2    3\n",
      "4    5\n",
      "6    7\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "ser_obj = pd.Series([1,3,5,7], index=[0,2,4,6])\n",
    "print(ser_obj[1:5])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d04715e5-0e57-4b92-859a-7ab1e8197521",
   "metadata": {},
   "source": [
    "如果希望获取的不是连续的数据，则可以通过不连续的索引来实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80f58d37-9b3e-44d1-a8f3-e95cbe3438b8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "d232ba12-5f5f-40e8-98a4-279dfaa5174b",
   "metadata": {},
   "source": [
    "将布尔值数组作为索引筛选数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "8ff5a72b-f7d0-4fb8-adeb-e9b9de56883a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0    False\n",
      "2     True\n",
      "4     True\n",
      "6     True\n",
      "dtype: bool\n",
      "2    3\n",
      "4    5\n",
      "6    7\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "ser_bool = ser_obj > 2\n",
    "print(ser_bool)\n",
    "\n",
    "#获取结果为True的数据\n",
    "print(ser_obj[ser_bool])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f7b3028-2471-4cde-9958-65c74cba7ec4",
   "metadata": {},
   "source": [
    "通过指定DataFrame列索引的操作来获取"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "412c4e0a-de0e-4f95-8bf1-4867cd50c74a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   a  b   c   d\n",
      "0  0  1   2   3\n",
      "1  4  5   6   7\n",
      "2  8  9  10  11\n",
      "\n",
      "0    1\n",
      "1    5\n",
      "2    9\n",
      "Name: b, dtype: int32\n",
      "\n",
      "<class 'pandas.core.series.Series'>\n",
      "\n",
      "   b   d\n",
      "0  1   3\n",
      "1  5   7\n",
      "2  9  11\n",
      "\n",
      "   a  b  c  d\n",
      "0  0  1  2  3\n",
      "1  4  5  6  7\n",
      "\n",
      "   b   d\n",
      "0  1   3\n",
      "1  5   7\n",
      "2  9  11\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "arr = np.arange(12).reshape(3, 4)\n",
    "#创建DataFrame对象，并为其指定索引\n",
    "df_obj = pd.DataFrame(arr, columns=['a', 'b', 'c', 'd'])\n",
    "print(df_obj)\n",
    "\n",
    "print()\n",
    "#通过索引取值\n",
    "print(df_obj['b'])    #获取b列的数据\n",
    "print()\n",
    "\n",
    "print(type(df_obj['b']))    #查看b列的类型\n",
    "print()\n",
    "\n",
    "print(df_obj[['b','d']])    #获取不连续的Series对象\n",
    "print()\n",
    "\n",
    "print(df_obj[:2])    #通过切片获取0-1行的数据\n",
    "print()\n",
    "\n",
    "#使用多个切片，先通过行索引获取第0-1行的数据\n",
    "#再通过不连续的列索引，获取 b d列的数据\n",
    "print(df_obj[:3][['b','d']])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b4a5137-9840-4abe-bee2-5d456221cb57",
   "metadata": {},
   "source": [
    "- 【虽然DataFrame的索引操作能够满足基本数据查看要求，但是仍然不够灵活，为此，Pandas库提供了操作索引的方法来访问数据，具体为：】\n",
    "- 【loc: 基于标签索引（索引名称，如a、b等），用于按标签选取数据。当执行切片操作时，既包含起始索引，也包含结束索引】\n",
    "- 【loc:基于位置索引（整数索引，如0到lengt-1）,用于按位置选取数据，当执行切片操作时，只包含起始索引，不包含结束索引】\n",
    "- 【【iloc: 方法主要使用整数来索引数据，而不能使用字符标签来索引数据. 而loc方法恰恰相反，他只能使用字符标签来索引数据，而不能使用整数来索引数据。不过，当DataFrame对象的行索引或列索引使用的是整数时，则其就可以使用整数来索引】】"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "1005b33f-ba07-4f2b-b388-affa72775ce4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   a  b   c   d\n",
      "0  0  1   2   3\n",
      "1  4  5   6   7\n",
      "2  8  9  10  11\n",
      "    c  a\n",
      "0   2  0\n",
      "1   6  4\n",
      "2  10  8\n",
      "    c  a\n",
      "0   2  0\n",
      "1   6  4\n",
      "2  10  8\n",
      "   b   c\n",
      "1  5   6\n",
      "2  9  10\n",
      "   b   c\n",
      "1  5   6\n",
      "2  9  10\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "agg = np.arange(16).reshape(4, 4)\n",
    "dataframe_obj = pd.DataFrame(arr, columns=['a', 'b', 'c', 'd'])\n",
    "print(dataframe_obj)\n",
    "\n",
    "#获取多行数据\n",
    "dataframe_loc = dataframe_obj.loc[:,[\"c\", \"a\"]]\n",
    "print(dataframe_loc)\n",
    "\n",
    "dataframe_iloc = datafeame_obj.iloc[:, [2, 0]]\n",
    "print(dataframe_iloc)\n",
    "\n",
    "#使用花式索引来访问数据\n",
    "df_flower_loc = dataframe_obj.loc[1:2, ['b','c']]\n",
    "print(df_flower_loc)\n",
    "\n",
    "df_flower_loc = datafeame_obj.iloc[1:3, [1,2]]\n",
    "print(df_flower_loc)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7d92ec7-4103-45ce-8404-68a2158f53b0",
   "metadata": {},
   "source": [
    "## "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
